#include "mainwindow.h"
#include "ui_mainwindow.h"


class UIntValidator : public QValidator {
public:
       UIntValidator(u_int32_t bottom, u_int32_t top, int base, QObject *parent = 0)
           : QValidator(parent), m_bottom(bottom), m_top(top), m_base(base)
       {
       }

       State validate(QString &input, int &pos) const
       {
           (pos);
           if (input.isEmpty())
               return Intermediate;
           bool ok;
           qlonglong val = input.toULongLong(&ok, m_base);
           if (!ok) {
               //qDebug("toULongLong invalid: base %d", m_base);
               return Invalid;
           }
           if (val < m_bottom) {
               //qDebug("toULongLong invalid %s %d", __func__, __LINE__);
               return Intermediate;
           } else if (val > m_top) {
               //qDebug("toULongLong invalid %s %d", __func__, __LINE__);
               return Invalid;
           } else {
               //qDebug("toULongLong invalid %s %d", __func__, __LINE__);
               return Acceptable;
           }
       }

private:
    u_int32_t m_bottom;
    u_int32_t m_top;
    int m_base;
};

#define BIT(x)  (1 << (x))
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    m_value = 0;

#define STATEMENT(index) m_btnarr[index] = ui->pb##index

    STATEMENT(0);
    STATEMENT(1);
    STATEMENT(2);
    STATEMENT(3);
    STATEMENT(4);
    STATEMENT(5);
    STATEMENT(6);
    STATEMENT(7);
    STATEMENT(8);
    STATEMENT(9);
    STATEMENT(10);
    STATEMENT(11);
    STATEMENT(12);
    STATEMENT(13);
    STATEMENT(14);
    STATEMENT(15);
    STATEMENT(16);
    STATEMENT(17);
    STATEMENT(18);
    STATEMENT(19);
    STATEMENT(20);
    STATEMENT(21);
    STATEMENT(22);
    STATEMENT(23);
    STATEMENT(24);
    STATEMENT(25);
    STATEMENT(26);
    STATEMENT(27);
    STATEMENT(28);
    STATEMENT(29);
    STATEMENT(30);
    STATEMENT(31);

    //QRegExp regx("[0-7]+$");
    //QValidator *octValidator = new QRegExpValidator(regx, ui->leOctValue);
    QValidator *decValidator = new UIntValidator(0, 4294967295, 10);
    ui->leDecValue->setValidator(decValidator);

    //QRegExp regHex("(0x)?[0-9a-fA-F]{1,8}$");
    //QValidator *HexValidator = new QRegExpValidator(regHex, ui->leHexValue);
    QValidator *HexValidator = new UIntValidator(0, 4294967295, 16);
    ui->leHexValue->setValidator(HexValidator);

    //ui->pb0->setStyleSheet("background-color: rgb(170, 0, 255);");
}

MainWindow::~MainWindow()
{
    delete ui;
}

#define BTN_CLICKED_FUNC(index) \
void MainWindow::bit##index##_clicked(bool checked)   \
{                                       \
    if (0) qDebug("%s pb%d m_value=0x%x checked=%d", __func__, index, m_value, checked);      \
    if (checked) {                      \
        m_value |= BIT(index);          \
        ui->pb##index->setText("1");    \
    } else {                            \
        m_value &= ~BIT(index);         \
        ui->pb##index->setText("0");    \
    }                                   \
    ui->leHexValue->setText(QString::number(m_value, 16).toUpper());    \
    ui->leDecValue->setText(QString::number(m_value, 10));               \
}

BTN_CLICKED_FUNC(31)
BTN_CLICKED_FUNC(30)
BTN_CLICKED_FUNC(29)
BTN_CLICKED_FUNC(28)
BTN_CLICKED_FUNC(27)
BTN_CLICKED_FUNC(26)
BTN_CLICKED_FUNC(25)
BTN_CLICKED_FUNC(24)
BTN_CLICKED_FUNC(23)
BTN_CLICKED_FUNC(22)
BTN_CLICKED_FUNC(21)
BTN_CLICKED_FUNC(20)
BTN_CLICKED_FUNC(19)
BTN_CLICKED_FUNC(18)
BTN_CLICKED_FUNC(17)
BTN_CLICKED_FUNC(16)

BTN_CLICKED_FUNC(15)
BTN_CLICKED_FUNC(14)
BTN_CLICKED_FUNC(13)
BTN_CLICKED_FUNC(12)
BTN_CLICKED_FUNC(11)
BTN_CLICKED_FUNC(10)
BTN_CLICKED_FUNC(9)
BTN_CLICKED_FUNC(8)
BTN_CLICKED_FUNC(7)
BTN_CLICKED_FUNC(6)
BTN_CLICKED_FUNC(5)
BTN_CLICKED_FUNC(4)
BTN_CLICKED_FUNC(3)
BTN_CLICKED_FUNC(2)
BTN_CLICKED_FUNC(1)
BTN_CLICKED_FUNC(0)

void MainWindow::hexValueChanged(QString v)
{
    bool ok;
    unsigned int value = v.toUInt(&ok, 16);
    unsigned int tmp = value;

    if (1) {
        for (int i = 0; i < 32; i++, value >>= 1) {
            m_btnarr[i]->setChecked(value & 0x1);
            m_btnarr[i]->setText(value & 0x1 ? "1" : "0");
		}
        ui->leDecValue->setText(QString::number(tmp, 10));
        m_value = tmp;
        //qDebug("%s m_value=0x%x", __func__, m_value);
    }
}

void MainWindow::decValueChanged(QString v)
{
    bool ok;
    unsigned int value = v.toUInt(&ok, 10);
    unsigned int tmp = value;

    if (1) {
        for (int i = 0; i < 32; i++, value >>= 1) {
            m_btnarr[i]->setChecked(value & 0x1);
            m_btnarr[i]->setText(value & 0x1 ? "1" : "0");
        }
        ui->leHexValue->setText(QString::number(tmp, 16));
        m_value = tmp;
        //qDebug("%s m_value=0x%x", __func__, m_value);
    }
}

void MainWindow::win_on_top(bool ontop)
{
    if (ontop) {
        this->setWindowFlags(this->windowFlags() | Qt::WindowStaysOnTopHint);
    } else {
        this->setWindowFlags(this->windowFlags() &~ Qt::WindowStaysOnTopHint);
    }

    this->show();
}
